#include <iostream>
#include <memory>
#include <cassert>
#include <sstream>
#include "serial.h"
#include "board.h"
#include "digital_pin.h"

using namespace std;
using namespace arduino;

class serialization_input;

class serializable
{
public:
	virtual void deserialize(serialization_input* input) = 0;
	virtual void* serialize() = 0;
	virtual size_t size() const = 0;
};

class serialization_input
{
	unsigned int pos_;
	size_t length_;
	void* buffer_;

public:
	serialization_input(void* data, size_t length) : 
	  pos_(0), buffer_(data), length_(length)
	{}

	template<typename T>
	T* read()
	{
		char* bytes = static_cast<char*>(buffer_);
		T* value = reinterpret_cast<T*>(bytes + pos_);
		pos_ += sizeof(T);
		return value;
	}
};

class gps_position : public serializable
{
public:
	struct coord 
	{
		coord() : lt(0), lng(0)
		{}

		int lt;
		int lng;
	};

	gps_position()
	{}

	coord coords() const
	{
		return coord_;
	}

	bool on_equator() const
	{
		return coord_.lt == 90;
	}
	
	void deserialize(serialization_input* input)
	{
		coord* c = input->read<coord>();
		coord_.lng = c->lng;
		coord_.lt = c->lt;
	}

	void* serialize()
	{
		return 0;
	}

	size_t size() const
	{
		return sizeof(coord);
	}

private:
	coord coord_;
};

int main()
{
	auto_ptr<serial> ser(new serial("COM3", 9600));
	auto_ptr<board> b(new board(ser.get()));
	digital_pin* pin13 = new digital_pin(13);

	b->register_pin(pin13);
	b->setup();
	cout << b->pin(13)->state() << endl;

	digital_pin* dpin13 = dynamic_cast<digital_pin*>(b->pin(13));

	delete pin13;

	gps_position::coord coords;
	coords.lng = 45;
	coords.lt = 99;

	serialization_input in(&coords, sizeof(gps_position::coord));

	gps_position gps;
	gps.deserialize(&in);
	cout << gps.coords().lng << endl;

	stringstream ss;
	ss << 12 << 43 << 55;
	cout << ss.str().c_str() << endl;

	system("PAUSE");
}
